package com.mccken.springframework.beans.factory.support;

import java.util.HashMap;
import java.util.Map;

import com.mccken.springframework.beans.BeansException;
import com.mccken.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.mccken.springframework.beans.factory.config.BeanDefinition;

import cn.hutool.core.bean.BeanException;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2022-11-19 23:38
 **/
public class DefaultListableBeanFactory extends AbstractAutowiredCapableBeanFactory implements BeanDefinitionRegistry, ConfigurableListableBeanFactory {
	
	private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
	
	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
		BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
		if (beanDefinition == null) {
			throw new BeansException("No bean named '" + beanName + "' is defined");
		}
		return beanDefinition;
	}

	@Override
	public void preInstantiateSingletons() throws BeansException {
		beanDefinitionMap.keySet().forEach(this::getBean);
	}

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beandefinition) {
		beanDefinitionMap.put(beanName, beandefinition);
	}

	@Override
	public boolean containsBeanDefinition(String beanName) {
		return beanDefinitionMap.containsKey(beanName);
	}

	@Override
	public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeanException {
		Map<String, T> result = new HashMap<>();
		beanDefinitionMap.forEach((beanName, beanDefinition) -> {
			Class beanClass = beanDefinition.getBeanClass();
			if (type.isAssignableFrom(beanClass)) {
				result.put(beanName, (T)getBean(beanName));
			}
		});
		return result;
	}

	@Override
	public String[] getBeanDefinitionNames() {
		return beanDefinitionMap.keySet().toArray(new String[0]);
	}
}
